#include "Render.h"
#include <iostream>

#pragma comment(lib, "Ole32.lib")

Render::Render() {
    CoInitialize(NULL);
    const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
    const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
    IMMDeviceEnumerator* pEnumerator = NULL;
    HRESULT hr = CoCreateInstance(
            CLSID_MMDeviceEnumerator, NULL,
            CLSCTX_ALL, IID_IMMDeviceEnumerator,
            (void**)&pEnumerator);

    if (hr != S_OK) { throw hr; }
    hr = pEnumerator->GetDefaultAudioEndpoint(
        eRender,
        eMultimedia,
        &this->defaultRender
    );
    if (hr != S_OK) {
        throw "could not obtian default system render. code " + hr;
    }

    if (S_OK != this->activeVolumeEndpoint()) {
        throw "could not active volume endpoint";
    }

    // this->activeVolumeCallBack();
}

Render::~Render() {
    this->defaultRender->Release();
}

float Render::getVolumeLevel() {
    IAudioEndpointVolume* volume = this->activedEndpointVolume;
    float ret = -1;
    volume->GetMasterVolumeLevelScalar(&ret);
    return ret;
}

void Render::setVolumeLevel(int level) {
    IAudioEndpointVolume* volume = this->activedEndpointVolume;
    volume->SetMasterVolumeLevelScalar(level / 100.0f, NULL);
}

HRESULT Render::activeVolumeEndpoint() {
    if (this->activedEndpointVolume != NULL) {
        this->activedEndpointVolume->Release();
    }

    const IID IID_IAudioEndpointVolume = __uuidof(IAudioEndpointVolume);
    return this->defaultRender->Activate(
        IID_IAudioEndpointVolume,
        CLSCTX_ALL,
        NULL,
        (void **) &this->activedEndpointVolume
    );
}

void Render::activeVolumeCallBack() {
    IAudioEndpointVolume* volume = this->activedEndpointVolume;
    if (this->activeVolumeEndpoint() == S_OK) {
        EndpointCallBackImpl* pEndpointCallBackImpl =new EndpointCallBackImpl();
        volume->RegisterControlChangeNotify(pEndpointCallBackImpl);
        std::cout << "callback actived" << std::endl;
    }
}

HRESULT STDMETHODCALLTYPE EndpointCallBackImpl::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify){
    std::cout << "master volume changed: " << pNotify->fMasterVolume << std::endl;
    return S_OK;
}